#include "Usuario.h"
// Macro para que no haya problemas con el formato UINT64
#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#ifdef _STDINT_H
#undef _STDINT_H
#endif
#include <stdint.h>
#endif
// Las librerias de ffmpeg son escritas en lenguaje C
extern "C" {
	#include <libavcodec/avcodec.h>
	#include <libavformat/avformat.h>
	#include <libavformat/avio.h>
	#include <libswscale/swscale.h>
}
#include <cstdio>
#include <gtkmm-2.4/gtkmm/main.h>
#include <glibmm-2.4/glibmm/refptr.h>
#include <gdkmm-2.4/gdkmm/window.h>
#include <gdkmm-2.4/gdkmm/drawable.h>
#include <gdkmm-2.4/gdkmm/pixbuf.h>
#include "CodificadorVideo.h"
#include <fstream>
#include <iostream>
using std::endl;
using std::cerr;
using std::cout;
using std::string;

Usuario::Usuario(string nombre_usuario, string clave, char* ip_serv,char* puerto, char* puerto_av) {
	this->nombre_usuario = nombre_usuario;
	this->clave = clave;
	this->socket = new Socket();
	this->serv_addr.sin_family = AF_INET;
	inet_aton(ip_serv, &(this->serv_addr.sin_addr));
	this->serv_addr.sin_port = htons(atoi(puerto));
	memset(&(this->serv_addr.sin_zero), '\0', 8);

	this->socket_av = new Socket();
	this->serv_addr_av.sin_family = AF_INET;
	inet_aton(ip_serv, &(this->serv_addr_av.sin_addr));
	this->serv_addr_av.sin_port = htons(atoi(puerto_av));
	memset(&(this->serv_addr_av.sin_zero), '\0', 8);
	conectado = false;
	receptor = NULL;
	reproductorVideo = new ReproductorVideo();
}

// instr_o_alumn = '0' si es instructor, sino es '1'
int Usuario::login(char instr_o_alumn) {
	cout << "Conectar al primer socket" << endl;
	if(!this->socket->conectar(&this->serv_addr)) {
		cerr << "No se conecto al 1" << endl;
		return -1;
	}
	cout << "conectar segundo socket" << endl;
	if(!this->socket_av->conectar(&this->serv_addr_av)) {
		cerr << "No se conecto al 2" << endl;
		return -1;
	}
	cout << "Conectado a ambos sockets" << endl;

	bool envio_ok;
	char cod_op = instr_o_alumn;
	int tam_arg = this->nombre_usuario.size() + this->clave.size() + 2;
	std::string aux = nombre_usuario + clave;
	std::cout << "Tamaño " << aux.size() << std::endl;
	std::cout << aux << std::endl;
	envio_ok = this->socket->enviar(&cod_op, sizeof(cod_op));
	if(!envio_ok)
		std::cerr << "no se pudo enviar" << std::endl;
	envio_ok = this->socket->enviar(&tam_arg, sizeof(tam_arg));
	if(!envio_ok)
		std::cerr << "no se pudo enviar" << std::endl;
	envio_ok = this->socket->enviar(this->nombre_usuario.c_str(), nombre_usuario.size() + 1);
	if(!envio_ok)
		std::cerr << "no se pudo enviar" << std::endl;
	envio_ok = this->socket->enviar(this->clave.c_str(), clave.size() + 1);
	if(!envio_ok)
		std::cerr << "no se pudo enviar" << std::endl;
	cout << "Envie: " << nombre_usuario << " " << clave << endl;
	this->crearHiloReceptor(reproductorVideo);
	conectado = true;
	return 0;
}

int Usuario::Inscribirse(std::string codClase) {
	bool envio_ok;
	char cod_op = 'A';
	int tam_arg = codClase.size() + 1;

	envio_ok = this->socket->enviar(&cod_op, sizeof(cod_op));
	if(!envio_ok)
		std::cerr << "no se pudo enviar" << std::endl;
	envio_ok = this->socket->enviar(&tam_arg, sizeof(tam_arg));
	if(!envio_ok)
		std::cerr << "no se pudo enviar" << std::endl;
	cout << "Se envio: " << codClase << " " << clave << endl;
	envio_ok = this->socket->enviar(codClase.c_str(), codClase.size() + 1);
	if(!envio_ok)
		std::cerr << "no se pudo enviar" << std::endl;
	return 0;
}

ReproductorVideo* Usuario::getReproductorVideo() {
	return(this->reproductorVideo);
}

Usuario::~Usuario() {
	if(conectado) {
		this->socket->shutDown();
		this->socket_av->shutDown();
	}
	delete this->socket;
	delete this->socket_av;
	if(receptor != NULL) {
		receptor->join();
		delete receptor;
	}
}
